home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / QuickDraw GX / QuickDraw GX Info / QuickDraw GX Interfaces / Interfaces & Libraries / graphics libraries / spline library.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-30  |  3.6 KB  |  115 lines  |  [TEXT/MPS ]

  1. /* graphics libraries:
  2.     Spline generation routines
  3.     by Cary Clark, Georgiann Delaney, Michael Fairman, Pablo Fernicola, Dave Good, Robert Johnson, Keith McGreggor, Oliver Steele, David Van Brink, Chris Yerga
  4.     Copyright 1987 - 1993 Apple Computer, Inc.  All rights reserved.    */
  5.  
  6. #include <Memory.h>
  7. #include "graphics libraries.h"
  8.  
  9. enum { onCurvePoint, offCurvePoint };
  10.  
  11. typedef struct
  12. {   long count;
  13.     unsigned long mask;
  14.     long control;
  15.     long *bits;
  16.     gxPoint *points;
  17. } splineBuild;
  18.  
  19. static void BeginSplineBuild(splineBuild *build, long *bits, gxPoint *points)
  20. {
  21.     build->count = 0;
  22.     build->mask = 0;
  23.     build->control = 0;
  24.     build->bits = bits;
  25.     build->points = points;
  26. }
  27.  
  28. static void EndSplineBuild(splineBuild *build)
  29. {   
  30.     if (build->mask) *build->bits = build->control;
  31. }
  32.  
  33. static void AddPoint(splineBuild *build, gxPoint *add, boolean offCurve)
  34. {
  35.     *build->points++ = *add;
  36.     if (build->mask == 0) build->mask = (-1UL >> 1) + 1;
  37.     if (offCurve) build->control |= build->mask;
  38.     if ((build->mask >>= 1) == 0)
  39.     {   *build->bits++ = build->control;
  40.         build->control = 0;
  41.     }
  42.     ++build->count;
  43. }
  44.  
  45. static void AddTangent(splineBuild *build, gxPoint *base, gxPoint *tangent, Fixed factor)
  46. {
  47.     gxPoint control;
  48.     control.x = base->x + FractMultiply(tangent->x, factor);
  49.     control.y = base->y + FractMultiply(tangent->y, factor);
  50.     AddPoint(build, &control, offCurvePoint);
  51. }
  52.  
  53. gxShape MirrorSpline(long count, gxPoint *points, fract slack, boolean closed)
  54. {
  55.     gxShape spline;
  56.     gxPoint *mine, *next;
  57.     Fixed prevLen, nextLen;
  58.     gxPoint prevDir, nextDir;
  59.     splineBuild build;
  60.     long actIndex, estCount = 3 * count, estIndex = 2 + (estCount + 31 >> 5);
  61.     long *storage = (long *)NewPtr(estIndex * sizeof(long) + estCount * sizeof(gxPoint));
  62.  
  63.     BeginSplineBuild(&build, storage + 2, (gxPoint *)(storage + estIndex));
  64.  
  65.     mine = next = points;
  66.     if (closed) mine += count - 1;
  67.     nextDir.x = next->x - mine->x;
  68.     nextDir.y = next->y - mine->y;
  69.     nextLen = Magnitude(nextDir.x, nextDir.y);
  70.     if (nextLen)
  71.     {   nextDir.x = FractDivide(nextDir.x, nextLen);
  72.         nextDir.y = FractDivide(nextDir.y, nextLen);
  73.     }
  74.  
  75.     while (count--)
  76.     {   mine = next;
  77.         if (count) ++next;
  78.         else if (closed) next = points;
  79.         prevLen = nextLen;
  80.         if (prevLen) prevDir = nextDir;
  81.         nextDir.x = next->x - mine->x;
  82.         nextDir.y = next->y - mine->y;
  83.         nextLen = Magnitude(nextDir.x, nextDir.y);
  84.         if (nextLen)
  85.         {   nextDir.x = FractDivide(nextDir.x, nextLen);
  86.             nextDir.y = FractDivide(nextDir.y, nextLen);
  87.             if (prevLen && slack)
  88.             {   gxPoint tangent;
  89.                 tangent.x = (prevDir.x >> 1) + (nextDir.x >> 1) >> 1;
  90.                 tangent.y = (prevDir.y >> 1) + (nextDir.y >> 1) >> 1;
  91.                 AddTangent(&build, mine, &tangent, -FractMultiply(slack, prevLen));
  92.                 if (nextLen != prevLen) AddPoint(&build, mine, onCurvePoint);
  93.                 AddTangent(&build, mine, &tangent, FractMultiply(slack, nextLen));
  94.             }
  95.             else goto addThis;
  96.         }
  97.         else if (!closed && count == 0)
  98.     addThis:    AddPoint(&build, mine, onCurvePoint);
  99.     }
  100.  
  101.     EndSplineBuild(&build);
  102.  
  103.     actIndex = 2 + (build.count + 31 >> 5);
  104.     if (actIndex < estIndex)
  105.         BlockMove(storage + estIndex, storage + actIndex, build.count * sizeof(gxPoint));
  106.     storage[0] = 1;
  107.     storage[1] = build.count;
  108.     spline = GXNewPaths((gxPaths *)storage);
  109.     if (closed) GXSetShapeFill(spline, gxClosedFrameFill);
  110.     else GXSetShapeFill(spline, gxOpenFrameFill);
  111.  
  112.     DisposePtr((Ptr)storage);
  113.     return spline;
  114. }
  115.